import Head from 'next/head';
import TableOptionsTable from '../../../components/prop-tables/TableOptionsTable';
import StateOptionsTable from '../../../components/prop-tables/StateOptionsTable';
import AlternateExample from '../../../examples/alternate-detail-panel';
import ChartDetailPanelExample from '../../../examples/chart-detail-panel';
import ExampleVirtualized from '../../../examples/enable-detail-panel-virtualized';
import ExampleConditional from '../../../examples/enable-detail-panel-conditionally';
import LazyDetailPanelExample from '../../../examples/lazy-detail-panel';

<Head>
  <title>{'Detail Panel Expanding Guide - Material React Table V3 Docs'}</title>
  <meta
    name="description"
    content="How to add expanding detail panels to each row in Material React Table"
  />
</Head>

## Detail Panel Feature Guide

Material React Table has multiple kinds of expanding features. This guide will show you how to use the detail panel feature to expand a single row to show more information for that row.

If you are looking for how to expand multiple rows from a tree data structure, see the [Expanding Sub-Rows](/docs/guides/expanding-sub-rows) guide.

### Relevant Table Options

<TableOptionsTable
  onlyOptions={
    new Set([
      'displayColumnDefOptions',
      'enableExpandAll',
      'muiDetailPanelProps',
      'muiExpandAllButtonProps',
      'muiExpandButtonProps',
      'positionExpandColumn',
      'renderDetailPanel',
    ])
  }
/>

### Relevant State

<StateOptionsTable onlyOptions={new Set(['expanded'])} />

### Render Detail Panel

To add a detail panel to a row, all you need to do is add a `renderDetailPanel` table option.

The recommended way to access the row data for the detail panel is to pull from the `original` object on a row. This gives you the original data for the row, not transformed or filtered by TanStack Table.

> Using `row.getValue('columnId')` will not work for data that does not have its own column. Using `row.original.columnId` is recommended for detail panels since the data in the detail panel usually does not have its own column.

### Disable Expand All Button

If you don't want to show the expand all button, you can set the `enableExpandAll` table option to `false`.

```jsx
const table = useMaterialReactTable({
  data,
  columns,
  enableExpandAll: false,
});
```

### Enable Detail Panel Conditionally Per Row

If the return value of your `renderDetailPanel` function returns `null` or a falsy value for a row, the expand button will be disabled for that row.

```jsx
const table = useMaterialReactTable({
  columns,
  data,
  renderDetailPanel: ({ row }) =>
    row.original.someCondition ? <DetailPanelContent /> : null,
});
```

One thing to note about the implementation of conditional detail panels is that additional `<tr>` elements will still be created for all rows, even if they do not have detail panel content. It is implemented this way in order to avoid bugs with row virtualization, or striped row CSS.

### Only Allow One Detail Panel Open At A Time

If you want to only allow one detail panel to be open at a time, all you have to do is add your own `onClick` logic to the `muiExpandButtonProps` table option.

```jsx
const table = useMaterialReactTable({
  data,
  columns,
  renderDetailPanel: ({ row }) => <DetailPanelContent />,
  muiExpandButtonProps: ({ row, table }) => ({
    onClick: () => table.setExpanded({ [row.id]: !row.getIsExpanded() }), //set only this row to be expanded
  }),
});
```

### Rotate Expand Icon

If you don't like the default rotation styles for the expand icons, you can pass in custom CSS to the `muiExpandButtonProps` and `muiExpandAllButtonProps` table options.

### Replace Expand Icon

You can easily use a custom expand icon either by following the [Custom Icons Guide](/docs/guides/custom-icons) or by passing in custom `children` to the `muiExpandButtonProps` and `muiExpandAllButtonProps` table options.

```jsx
const table = useMaterialReactTable({
  data,
  columns,
  // icons, //or manage icons globally
  muiExpandButtonProps: ({ row }) => ({
    children: row.getIsExpanded() ? <MinusIcon /> : <AddIcon />,
  }),
});
```

### Customize or Style Detail Panel

You can use the `muiDetailPanelProps` table option to pass in custom props to the detail panel. These props are passed to the `<td>` element that contains the detail panel content.

If you need to customize the `<tr>` element containing the detail panel cell, you can just use the `muiTableBodyRowProps` table option that you use for customizing all rows. There is a `isDetailPanel` parameter that is available to you to target only detail panel rows.

```jsx
const table = useMaterialReactTable({
  data,
  columns,
  muiDetailPanelProps: ({ row }) => ({
    sx: {
      //...
    },
  }),
  muiTableBodyRowProps: ({ isDetailPanel, row }) => ({
    sx: {
      // isDetailPanel ? ... : ...
    },
  }),
});
```

<ExampleConditional />

### Expand Detail Panel By Default

If you want some or all rows to be expanded by default, you can specify that in the `initialState.expanded` table option. Pass `true` to expand all rows, or specify which rowIds should be expanded.

```jsx
const table = useMaterialReactTable({
  data,
  columns,
  initialState: {
    expanded: true,
    // or expand specific rows by default
    // expanded: {
    //   1: true,
    //   2: true,
    // },
  },
});
```

### Position Expand Column Last

If you want to position the expand column last, you can set the `positionExpandColumn` table option to `'last'`.

Alternatively though, you could use the [Column Pinning Feature](/docs/guides/column-pinning) to pin the expand column to the right side of the table.

<AlternateExample />

### Detail Panel With Charts

The detail panel can be used to show a variety of content. Here's an example of a detail panel rendering charts with the [MUI X Charts](https://mui.com/x/react-charts/getting-started/) library.

<ChartDetailPanelExample />

### Detail Panels with Virtualization

> New in v2.6.0

If you are using row virtualization, detail panels will now work more properly as of version 2.6.0. However, there are some caveats to be aware of. In order for row virtualization to work well, many of the animation/transitions have been disabled. This means that the detail panel will not animate open and closed. It will simply appear and disappear.

You also may need to specify some more accurate row height estimations for the row virtualizer in order to achieve the best scrollbar behavior. See the [Row Virtualization Guide](/docs/guides/row-virtualization) for the full details on this topic, but here's an example of how you might do that.

```jsx
const table = useMaterialReactTable({
  data,
  columns,
  enableRowVirtualization: true,
  renderDetailPanel: ({ row }) => <DetailPanelContent />,
  rowVirtualizerOptions: ({ table }) => {
    const { density, expanded } = table.getState();
    return {
      //adjust to your needs
      estimateSize: (index) =>
        index % 2 === 1 //even rows are normal rows, odd rows are detail panels
          ? //Estimate open detail panels as 80px tall, closed detail panels as 0px tall
            expanded === true
            ? 80
            : 0
          : //estimate normal row heights
            density === 'compact'
            ? 37
            : density === 'comfortable'
              ? 58
              : 73,
    };
  },
});
```

<ExampleVirtualized />

### Lazy Detail Panels

Fetching the additional data for the detail panels only after the user clicks to expand the row can be a good way to improve performance, and it is pretty easy to implement. It's even easier if you are using React Query.

<LazyDetailPanelExample />

View Extra Storybook **[Examples](https://www.material-react-table.dev/?path=/story/features-detail-panel-examples-)**
